<?php
    /*

     Version: MPL 1.1

     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
     License for the specific language governing rights and limitations
     under the License.

     The Original Code is KASSIOP Framework.

     The Initial Developer of the Original Code is SURIAN Nicolas (aka NairuS) <me@nairus.fr>.
     Portions created by the Initial Developer are Copyright (C) 2010
     The Initial Developer. All Rights Reserved.

     Contributor(s):

     Alternatively, the contents of this file may be used under the terms
     of the MPL license Version 1.1 (the  "MPL" License"), in which case the
     provisions of Version: MPL 1.1 License are applicable instead of those
     above.  If you wish to allow use of your version of this file only
     under the terms of the MPL License and not to allow others to use
     your version of this file under the MPL, indicate your decision by
     deleting  the provisions above and replace  them with the notice and
     other provisions required by the MPL License.  If you do not delete
     the provisions above, a recipient may use your version of this file
     under either the MPL License.

     The contents of this file are subject to the Mozilla Public License
     Version 1.1 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.mozilla.org/MPL/

    */

    /**
     * HtmlHelper class
     *
     * Builds html tags for the application
     *
     * @package    kassiop.system
     * @subpackage helpers
     *
     * @author NairuS
     * @version 1.2 $Rev: 90 $ $Date: 2011-01-16 09:23:26 +0000 (Sun, 16 Jan 2011) $ $Author: nicolas.surian $
     *
     */
    class HtmlHelper
    {
        /**
         * Returns the button input tag to build.
         *
         * @param array  $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function button( array $htmloptions = array() )
        {
            $htmloptions['type'] = 'button' ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the checkbox input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param array   $htmloptions  The html options to build.
         * @param boolean $selected     Defines if the input is checked or not.
         * @return string of the 'input' tag to build.
         */
        public static function checkbox( $name, array $htmloptions = array(), $selected = false )
        {
            $htmloptions['name'] = $name ;
            $htmloptions['type'] = 'checkbox';
            $htmloptions = self::_addChecked( $htmloptions, $selected ) ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Builds and returns a date select tag.
         *
         * @param  string  $name
         * @param  array   $years
         * @param  array   $monthes
         * @param  boolean $empty
         * @param  mixed   $selected The value to selected (mysql date). ex: 2010-01-31
         * @return string
         */
        public static function date( $name, array $years = array(), array $monthes = array(), $empty = false, $selected = false )
        {
            Configuration::setDefaultTimeZone();

            $dateSelected  = $selected !== false ? getdate( strtotime( $selected ) ) : null ;
            $daySelected   = false ;
            $monthSelected = false ;
            $yearSelected  = false ;
            $htmlTag       = '';

            if( !empty( $dateSelected ) )
            {
                if( $dateSelected['mday'] < 10 )
                {
                    $daySelected = (string)'0' . $dateSelected['mday'];
                }
                else
                {
                    $daySelected = (string)$dateSelected['mday'];
                }
                if( $dateSelected['mon'] < 10 )
                {
                    $monthSelected = (string)'0' . $dateSelected['mon'];
                }
                else
                {
                    $monthSelected = (string)$dateSelected['mon'];
                }
                $yearSelected = (string)$dateSelected['year'];
            }

            // fill days datas.
            for( $i = 1; $i <= 31; $i++ )
            {
                if( $i < 10 )
                {
                    $day = (string)'0' . $i;
                }
                else
                {
                    $day = (string)$i;
                }
                $days[$day] = $day;
            }

            // fill monthes datas.
            if( empty( $monthes ) )
            {
                $monthes = array(
                    '01' => 'Janvier',
                    '02' => 'F&eacute;vrier' ,
                    '03' => 'Mars',
                    '04' => 'Avril',
                    '05' => 'Juin',
                    '06' => 'Juillet' ,
                    '07' => 'Ao&ucirc;t',
                    '08' => 'Septembre',
                    '10' => 'Octobre',
                    '11' => 'Novembre' ,
                    '12' => 'D&eacute;cembre',
                );
            }

            // fill years datas.
            if( empty( $years ) )
            {
                $today = getdate();
                $i     = $today['year'] - 100;
                for($i; $i <= $today['year']; $i++ )
                {
                    $years[$i] = $i ;
                }
            }

            $htmlTag .= self::select( $name . '[day]', $days, array( 'id' => $name . '_day' ), $empty, $daySelected );
            $htmlTag .= self::select( $name . '[month]', $monthes, array( 'id' => $name . '_month' ), $empty, $monthSelected );
            $htmlTag .= self::select( $name . '[year]', $years, array( 'id' => $name . '_year' ), $empty, $yearSelected );

            return $htmlTag;
        }

        /**
         * Builds and returns a datetime select tags.
         *
         * @param  string  $name
         * @param  array   $years
         * @param  array   $monthes
         * @param  boolean $empty
         * @param  mixed   $selected The value to selected (mysql datetime). ex: 2010-01-31 23:59:59
         * @param  boolean $withSeconds
         *
         * @return string
         */
        public static function dateTime( $name, array $years = array(), array $monthes = array(), $empty = false, $selected = false, $withSeconds = false )
        {
            $htmlTag         = self::date( $name, $years, $monthes, $empty, $selected );
            $timeSelected    = $selected !== false ? getdate( strtotime( $selected ) ) : null;
            $hoursSelected   = false ;
            $minutesSelected = false ;
            $secondsSelected = false ;

            if( !empty($timeSelected) )
            {
                if( $timeSelected['hours'] < 10 )
                {
                    $hoursSelected = (string)'0' . $timeSelected['hours'];
                }
                else
                {
                    $hoursSelected = (string)$timeSelected['hours'];
                }
                if( $timeSelected['minutes'] < 10 )
                {
                    $minutesSelected = (string)'0' . $timeSelected['minutes'];
                }
                else
                {
                    $minutesSelected = (string)$timeSelected['minutes'];
                }
                if( $timeSelected['seconds'] < 10 )
                {
                    $secondsSelected = (string)'0' . $timeSelected['seconds'];
                }
                else
                {
                    $secondsSelected = (string)$timeSelected['seconds'];
                }
            }

            // fill all the elements.
            $hours   = array();
            $minutes = array();
            $seconds = array();

            for( $i = 0; $i <= 23; $i++ )
            {
                $value = (string)$i;
                if( $i < 10 )
                {
                    $value           = (string)'0' . $i;
                    $hours[$value]   = $value;
                    $minutes[$value] = $value;
                    $seconds[$value] = $value;
                }
                else
                {
                    $hours[$i]   = $value;
                    $minutes[$i] = $value;
                    $seconds[$i] = $value;
                }
            }

            // fill only the minutes and the seconds.
            for( $i = 24; $i <= 59; $i++ )
            {
                $value       = (string)$i;
                $minutes[$i] = $value;
                $seconds[$i] = $value;
            }
            $htmlTag .= self::select( $name . '[hour]'  , $hours  , array( 'id' => $name . '_hour' )  , $empty, $hoursSelected );
            $htmlTag .= self::select( $name . '[minute]', $minutes, array( 'id' => $name . '_minute' ), $empty, $minutesSelected );

            if( $withSeconds )
            {
                $htmlTag .= self::select( $name . '[second]', $seconds, array( 'id' => $name . '_second' ), $empty, $secondsSelected );
            }
            return $htmlTag;
        }

        /**
         * Returns a span tag formatted for form errors.
         *
         * @param  string  $message
         * @param  boolean $withBR
         * @return string
         */
        public static function errorForm( $message, $withBR = false )
        {
            $BR = $withBR ? '<br />' : '';
            return <<<EOF
<span class="error">$message</span>$BR
EOF;
        }

        /**
         * Return a form open tag formatted
         *
         * @param  string  $action
         * @param  array   $htmloptions
         * @param  boolean $file
         * @param  string  $method
         * @return string
         */
        public static function form( $action, array $htmloptions = array(), $file = false, $method = 'post')
        {
            $htmloptions['action']  = $action;
            $htmloptions['enctype'] = 'application/x-www-form-urlencoded';
            $htmloptions['method']  = $method;
            if( $file )
            {
                $htmloptions['enctype'] = 'multipart/form-data' ;
            }
            $options = self::_buildOptions( $htmloptions );
            return <<<EOF
<form$options>
EOF;
        }

        /**
         * Returns the file input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param array   $htmloptions
         * @param array   $mimeTypes    The list of mime types accepted by the tag.
         * @return string of the 'input' tag to build.
         */
        public static function file( $name, array $htmloptions = array(), array $mimeTypes = array() )
        {
            $htmloptions['name'] = $name ;
            $htmloptions['type'] = 'file' ;

            if( !empty( $mimeTypes ) )
            {
                $htmloptions['accept'] = implode( ', ', $mimeTypes ) ;
            }
            else
            {
                // remove accept key if setted in $htmloptions parameter.
                if( isset( $htmloptions['accept'] ) )
                {
                    unset( $htmloptions['accept'] ) ;
                }
            }
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the hidden input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param string  $value        The value attribute of the tag (required).
         * @param array   $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function hidden( $name, $value, array $htmloptions = array() )
        {
            $htmloptions['name']  = $name ;
            $htmloptions['value'] = $value ;
            $htmloptions['type']  = 'hidden' ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the 'img' tag for this link to build.
         *
         * @param string $src
         * @param string $alt
         * @param array  $htmloptions
         * @return string of the 'img' tag to build.
         */
        public static function image( $src, $alt = null, array $htmloptions = array() )
        {
            $options = self::_buildOptions( $htmloptions ) ;
            return <<<EOF
<img src="$src" alt="$alt"$options />
EOF;
        }

        /**
         * Returns the image input tag to build.
         *
         * @param string  $src          The src attribute of the tag (required).
         * @param string  $alt          The alt attribute of the tag (must be written even null).
         * @param array   $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function inputImage( $src, $alt = "", array $htmloptions = array() )
        {
            $htmloptions['alt']  = $alt ;
            $htmloptions['src']  = $src ;
            $htmloptions['type'] = 'image' ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the text input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param array   $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function inputText( $name, array $htmloptions = array() )
        {
            $htmloptions['name'] = $name ;
            $htmloptions['type'] = 'text' ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the 'a' tag for this link to build.
         *
         * @param string  $title
         * @param string  $uri
         * @param array   $htmloptions
         * @param mixed   $confirm defines if the link has an JS confirmation.
         * @return string of the 'a' tag for this link to build.
         */
        public static function linkTo( $title, $uri, array $htmloptions = array(), $confirm = false )
        {
            // delete href key if it is declared in $htmloption parameter twice.
            if( key_exists( 'href', $htmloptions ) )
            {
                unset( $htmloptions['href'] );
            }

            $onclick = '';
            if( $confirm !== false )
            {
                // delete onclick key if it is declared in $htmloption parameter to avoir conflict.
                if( key_exists( 'onclick', $htmloptions ) )
                {
                    unset( $htmloptions['onclick'] );
                }
                $onclick = <<<EOF
 onclick="return confirm('$confirm');"
EOF;
            }

            $options = self::_buildOptions( $htmloptions ) ;

            return <<<EOF
<a href="$uri"$options$onclick>$title</a>
EOF;
        }

        /**
         * Return a mailTo a tag protected from bots.
         *
         * @param  string $email
         * @param  string  $htmlOptions
         * @return string
         */
        public static function mailTo( $email, array $htmlOptions = array() )
        {
            $mailto  = StringsHelper::sanitizeEmail( $email );
            $htmlOptions['href'] = 'mailto:' . $mailto . ';';
            $options = self::_buildOptions( $htmlOptions ) ;
            $texte   = split("@", $email);

            $tag     = <<<EOF
<a$options><span>$texte[0]</span>&#64;<span>$texte[1]</span></a>
EOF;
            return $tag;
        }

        /**
         * Formats an string in a p tag.
         *
         * @param string $string
         * @return string
         */
        public static function paragraphe( $string, array $htmlOptions = array() )
        {
            $options = self::_buildOptions( $htmlOptions ) ;
            return <<<EOF
<p$options>$string</p>
EOF;
        }

        /**
         * Returns the password input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param array   $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function password( $name, array $htmloptions = array() )
        {
            $htmloptions['name'] = $name ;
            $htmloptions['type'] = 'password' ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Returns the radio input tag to build.
         *
         * @param string  $name         The name attribute of the tag (required).
         * @param string  $value        The value attribute of the tag (required).
         * @param array   $htmloptions
         * @param boolean $selected
         * @return string of the 'input' tag to build.
         */
        public static function radio( $name, $value, array $htmloptions = array(), $selected = false )
        {
            $htmloptions['name']  = $name . '[]';
            $htmloptions['value'] = $value;
            $htmloptions['type']  = 'radio';
            $htmloptions = self::_addChecked( $htmloptions, $selected ) ;
            return self::input( $htmloptions ) ;
        }

        /**
         * Render the global errors of the model if exists.
         *
         * @param  ErrorsModelManager $manager
         * @return string
         */
        public static function renderGlobalErrors( ErrorsModelManager $manager )
        {
            if( $manager->hasGlobalErrors() )
            {
                $errors = array();
                foreach( $manager->getGlobalErrors() as $vo )
                {
                    if( $vo instanceof ErrorVO )
                    {
                        array_push( $errors, $vo->message );
                    }
                }
                return self::ul( $errors, array( 'class' => 'errors' ) ) ;
            }
            return null;
        }

        /**
         * Render the error of the model if exists.
         *
         * @param  ErrorsModelManager $manager
         * @param  string             $field
         * @return string
         */
        public static function renderModelError( ErrorsModelManager $manager, $field )
        {
            if( $manager->hasError( $field ) )
            {
              return self::errorForm(
                $manager->getError( $field )->message, true ) ;
            }
            return null;
        }

        /**
         * Returns the reset input tag to build.
         *
         * @param array   $htmloptions  The html options to build.
         * @param boolean $selected     Defines if the input is checked or not.
         * @return string of the 'input' tag to build.
         */
        public static function reset( array $htmloptions = array() )
        {
            $htmloptions['type']  = 'reset';
            if( !isset( $htmloptions['value'] ) )
            {
                $htmloptions['value'] = 'Cancel';
            }

            return self::input( $htmloptions ) ;
        }

        /**
         * Create a select tag standard.
         *
         * @param  array   $name         The name attribute of the tag (required).
         * @param  array   $datas        The datas to fill the list.
         * @param  array   $htmlOptions  The html options for the tag.
         * @param  boolean $empty        Add empty option if true.
         * @return string
         */
        public static function select( $name, array $datas = array(), array $htmlOptions = array(), $empty = false, $selected = false )
        {
            $htmlOptions['name'] = $name ;
            $options             = self::_buildOptions( $htmlOptions ) ;
            $tag                 = <<<EOF
<select$options>
EOF;
            if( $empty === true )
            {
                $tag .= <<<EOF
<option value=""></option>
EOF;
            }
            foreach( $datas as $key => $value )
            {
                $isSelected = '' ;
                if( $selected !== false )
                {
                    if( is_array( $selected ) )
                    {
                        foreach( $selected as $value )
                        {
                            if( $key == $value )
                            {
                                $isSelected = ' selected="selected"' ;
                                break ;
                            }
                        }
                    }
                    else
                    {
                        if( $key == $selected )
                        {
                            $isSelected = ' selected="selected"' ;
                        }
                    }
                }

                $tag .= <<<EOF
<option value="$key"$isSelected>$value</option>
EOF;
            }
            $tag .= <<<EOF
</select>
EOF;
        return $tag ;
        }

        /**
         * Returns the submit input tag to build.
         *
         * @param array  $htmloptions
         * @return string of the 'input' tag to build.
         */
        public static function submit( array $htmloptions = array() )
        {
            if( !isset( $htmloptions['value'] ) )
            {
                $htmloptions['value'] = 'Submit';
            }
            $htmloptions['type'] = 'submit';
            return self::input( $htmloptions ) ;
        }

        /**
         * Return the UI icon.
         *
         * @param  string $icon
         * @return string
         */
        public static function UIButton( $icon )
        {
            $uiIcon = self::UIIcon( $icon );
            return <<<EOF
<div class="ui-button ui-state-default ui-corner-all" title=".ui-icon-$icon">$uiIcon</div>
EOF;
        }

        /**
         * Return the UI icon.
         *
         * @param  string $icon
         * @return string
         */
        public static function UIIcon( $icon )
        {
            return <<<EOF
<span class="ui-icon ui-icon-$icon">&nbsp;</span>
EOF;
        }

        /**
         * Render a ul tag with its li or ol elements.
         *
         * @param  array   $values
         * @param  array   $htmloptions
         * @param  boolean $ordonate
         * @return string
         */
        public static function ul( array $values = array(), array $htmloptions = array(), $ordonate = false )
        {
            if( !empty( $values ) )
            {
                $options = self::_buildOptions( $htmloptions );
                $list = '<ul' . $options . '>';
                if( $ordonate === true )
                {
                    $openTag = '<ol>';
                    $endTag  = '</ol>';
                }
                else
                {
                    $openTag = '<li>';
                    $endTag  = '</li>';
                }
                foreach( $values as $value )
                {
                    $list .= $openTag . $value . $endTag;
                }
                $list .= '</ul>';
                return $list;
            }
            return '';
        }

        /**
         * Returns a textarea tag formatted.
         *
         * @param  string  $name
         * @param  string  $value
         * @param  integer $cols
         * @param  integer $rows
         * @param  array   $htmlOptions
         * @return string
         */
        public static function textArea( $name, $value = null, $cols = 50 , $rows = 5,  array $htmlOptions = array() )
        {
            $htmlOptions['name'] = $name ;
            $htmlOptions['cols'] = $cols ;
            $htmlOptions['rows'] = $rows ;
            $options             = self::_buildOptions( $htmlOptions ) ;
            $tag                 = <<<EOF
<textarea$options>$value</textarea>
EOF;
            return $tag;
        }

        /**
         * Add checked option for radio or checkbox input.
         *
         * @param  array   $htmloptions
         * @param  boolean $selected
         * @return array
         */
        private static function _addChecked( array $htmloptions = array(), $selected = false )
        {
            if( $selected === true )
            {
                $htmloptions['checked'] = 'checked';
            }
            return $htmloptions ;
        }

        /**
         * Builds the html options passed-in for a tag.
         *
         * @param  array $htmloptions
         * @return string
         */
        private static function _buildOptions( array $htmloptions = array() )
        {
            $options = null ;

            if( !empty( $htmloptions ) )
            {
                $options = '' ;
                foreach( $htmloptions as $attr => $val )
                {
                    $options .= <<<EOF
 $attr="$val"
EOF;
                }
            }
            return $options ;
        }

        /**
         * Returns the 'input' tag for this link to build.
         *
         * @param array  $htmloptions
         * @return string of the 'input' tag to build.
         */
        private static function input( array $htmloptions = array() )
        {
            $options = self::_buildOptions( $htmloptions ) ;
            return <<<EOF
<input$options />
EOF;
        }
    }
?>